VE_STRUCT_TIMESPEC

#include <iostream>
#include <queue>
#include <string>
#include <pthread.h>

//#include <thread>
//#include <sys/prctl.h>

using std::cout;
using std::endl;

template<class T>
class ThreadPool
{
public:
	ThreadPool(int ThreadNum)
		:ThreadNum_(ThreadNum)
	{
		pthread_mutex_init(&mutex_, nullptr);
		pthread_cond_init(&cond_, nullptr);
	};
	~ThreadPool()
	{
		pthread_mutex_destroy(&mutex_);
		pthread_cond_destroy(&cond_);
	}
public:
	static void* Routine(void* args)
	{
		pthread_detach(pthread_self());//不关心返回值,不用join
		// static函数    所以传this过来访问类内函数
		ThreadPool<T>* tp = static_cast<ThreadPool<T>*> (args);
		//prctl(PR_SET)..
		
		//cout << "Routine:" << pthread_self() << endl;
		while (true)
		{
			tp->LockQueue();
			while (!tp->HaveTask())
			{
				cout << "while..." << endl;
				tp->WaitForTask();
			}
			//cout << "start task " << pthread_self() << endl;
			//有任务来了线程去处理
			T t = tp->pop();//拿到阻塞队列的任务
			tp->UnLockQueue();

			//for debug
			int one, two;
			char op;
			t.get(&one, &two, &op);
			cout << "新线程完成计算任务：" << one << op << two << "=" << t.run() << endl;
		}
	}

	void start()
	{
		while (ThreadNum_--)
		{
			pthread_t tmp;
			pthread_create(&tmp, nullptr, Routine, this);
		}
	}

	//push 和 pop 的加锁和解锁要仔细想想
    //push 是在 main 函数里面push的，一下是只有一个的
    //但是pop不加锁是因为pop调用的时候本身就已经有锁了，所以
    //再次加锁就会产生死锁现象！
	void push(T t)
	{
		LockQueue();
		//cout << "主线程 push" << pthread_self() << endl;
		TaskQueue_.push(t);
		ChoiceThreadToHandler();
		UnLockQueue();
	}

private:
	void LockQueue() { pthread_mutex_lock(&mutex_);};
	void UnLockQueue() { pthread_mutex_unlock(&mutex_);};
	void WaitForTask() { pthread_cond_wait(&cond_, &mutex_); };//P && 释放锁
	void ChoiceThreadToHandler() { pthread_cond_signal(&cond_); };
	bool HaveTask() { return !TaskQueue_.empty(); };

	T pop()
	{
		//cout << "pop " << pthread_self() << endl;
		T head = TaskQueue_.front();
		TaskQueue_.pop();
		return head;
	}
private:
	int ThreadNum_;
	pthread_mutex_t mutex_;
	pthread_cond_t cond_;
	std::queue<T> TaskQueue_;
};
